home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Just Call Me Internet
/
Just Call Me Internet.iso
/
prog
/
atari
/
m2
/
cat3src
/
putz
/
putzgrou.i
< prev
next >
Wrap
Text File
|
1997-10-26
|
62KB
|
2,090 lines
IMPLEMENTATION MODULE PutzGroup;
FROM SYSTEM IMPORT ADDRESS, ADR, CADR, ASSEMBLER, CAST, TSIZE;
(* MM2-Module *)
IMPORT Block, BinOps, Strings, StrConv, Lists, Storage;
(* CAT-Module *)
IMPORT ZCalcCrc, dataSys, MTPaths, CatFiles, GroupSelect;
FROM Void IMPORT v;
FROM dataSys IMPORT posType;
(* Magic-Module *)
IMPORT MagicDOS, mtAlerts, MagicCookie, mtTextfiles;
(* Putz-Module *)
IMPORT PutzAction, PutzTypes, PutzLog;
FROM PutzTypes IMPORT delState, totalEntry, putzList;
CONST deletedText = '<gelscht von CatPutz '+PutzTypes.xVersion+'>'+12C+0C;
CONST fDiskFull = -1004;
fReadError = -1005;
TYPE fileHandle = INTEGER;
VAR
putzOpts : PutzTypes.putzOptsRec;
VAR datFile,
parFile,
tabFile : fileHandle;
newDat,
newPar,
newTab : fileHandle;
datSize : LONGCARD;
newNums : ARRAY [0..65535] OF CARDINAL;
tabArray : PutzTypes.ptrTabArray;
parArray : PutzTypes.parFilePtr;
newTabArray : PutzTypes.ptrTabArray;
newParArray : PutzTypes.parFilePtr;
datBuffer: POINTER TO ARRAY[0L..$FFFFFFFFL] OF CHAR;
buf : POINTER TO ARRAY [0..79999] OF CHAR; (* globaler Buffer *)
datBuffered,
tabBuffered,
parBuffered : BOOLEAN;
msgCounter : CARDINAL; (* Counter fr neue Messagefiles *)
bRead : LONGCARD;
badMsg,
partDeleted,
deleted : CARDINAL;
firstUnread,
unreadCounter : CARDINAL;
currentGroup : INTEGER;
AnzMessages : CARDINAL;
hasFileLocking: BOOLEAN;
stopDelete : BOOLEAN;
PROCEDURE MFree (VAR adr : ADDRESS) : BOOLEAN;
VAR res : BOOLEAN;
BEGIN
res := MagicDOS.Mfree (adr);
adr := NIL;
RETURN res;
END MFree;
PROCEDURE MemAvail () : LONGCARD;
BEGIN
RETURN LONGCARD(MagicDOS.Malloc (MagicDOS.Minus1));
END MemAvail;
PROCEDURE WriteBytes (f: fileHandle; addr: ADDRESS; bytes: LONGCARD);
(* Speichert die Daten ab Adresse 'addr' mit der Lnge 'bytes' in Byte *)
VAR count : LONGCARD;
state : INTEGER;
BEGIN
count := bytes;
MagicDOS.Fwrite (f, count, addr);
IF count # bytes
THEN
IF LONGINT (count) < 0
THEN
(* GEMDOS-Fehler *)
state := VAL (INTEGER, SHORT(count));
ELSE
state := fDiskFull;
END;
ELSE
state := 0;
END;
IF state < 0 THEN
CatFiles.ErrorAlert (state);
stopDelete := TRUE;
END;
END WriteBytes;
PROCEDURE ReadBytes ( f : fileHandle; addr : ADDRESS; bytes : LONGCARD;
VAR bytesRead: LONGCARD);
VAR state : INTEGER;
BEGIN
bytesRead := bytes;
MagicDOS.Fread (f, bytesRead, addr);
IF bytesRead # bytes
THEN
IF LONGINT (bytesRead) < 0
THEN
(* GEMDOS-Fehler *)
state := VAL (INTEGER, SHORT(bytesRead));
ELSE
state := fReadError;
END;
ELSE
state := 0;
END;
IF state < 0 THEN
CatFiles.ErrorAlert (state);
stopDelete := TRUE;
END;
END ReadBytes;
VAR buffer : POINTER TO ARRAY [$0L..$FFFFFFFFL] OF CHAR;
bufPos, bufSize : LONGCARD;
bufHdl : fileHandle;
bytesWritten : LONGCARD;
PROCEDURE FilePos (f: fileHandle): LONGCARD;
(*
* Liefert aktuelle Byteposition des Dateizeigers.
*)
VAR fp : LONGCARD;
BEGIN
IF (f = bufHdl)
THEN
fp := bytesWritten
ELSE
fp := MagicDOS.Fseek (0, f, MagicDOS.SeekPos);
IF (f = bufHdl) & (buffer # NIL) & (bufSize > 0)
THEN
INC (fp, bufPos);
END;
END;
RETURN fp;
END FilePos;
PROCEDURE FileSize (f: fileHandle): LONGCARD;
VAR fp: LONGCARD;
size : LONGCARD;
BEGIN
fp := MagicDOS.Fseek (0, f, MagicDOS.SeekPos);
IF fp # 0
THEN
v.lcard := MagicDOS.Fseek (0, f, MagicDOS.SeekStart);
END;
size := MagicDOS.Fseek (0, f, MagicDOS.SeekEnd);
(* Position wieder restaurieren *)
fp := MagicDOS.Fseek (fp, f, MagicDOS.SeekStart);
RETURN size;
END FileSize;
PROCEDURE OpenFile (VAR f: fileHandle; REF name: ARRAY OF CHAR);
VAR mode : BITSET;
BEGIN
mode := {MagicDOS.ReadWrite};
IF hasFileLocking
THEN
(* Jeglichen anderen Zugriff verbieten *)
INCL (mode, MagicDOS.ShareFlag1);
END;
f := MagicDOS.Fopen (name, mode);
END OpenFile;
PROCEDURE CreateFile (VAR f: fileHandle; REF name: ARRAY OF CHAR);
BEGIN
f := MagicDOS.Fcreate (name, {});
END CreateFile;
PROCEDURE WriteBuffered (fHdl : fileHandle; buf : ADDRESS; l : LONGCARD);
VAR (*$Reg*) remain : LONGCARD;
(*$Reg*) wrBytes : LONGCARD;
(*$Reg*) ptr : POINTER TO ARRAY [0..$FFFFFFFF] OF CHAR;
BEGIN
IF bufSize = 0
THEN
WriteBytes (fHdl, buf, l);
ELSIF l+bufPos > bufSize
THEN
remain := l;
REPEAT
Block.Copy (buf, bufSize-bufPos, ADR(buffer^[bufPos]));
INC (buf, bufSize-bufPos);
DEC (remain, bufSize-bufPos);
INC(bufPos, bufSize-bufPos);
wrBytes := bufPos;
WriteBytes (fHdl, buffer, bufPos);
IF bufPos # wrBytes
THEN
INC (bytesWritten, l - remain);
l := bufPos;
RETURN
END;
bufPos := 0;
UNTIL remain < bufSize;
Block.Copy (buf, remain, ADR(buffer^[bufPos]));
bufPos := remain;
ELSE
Block.Copy (buf, l, ADR(buffer^[bufPos]));
INC(bufPos,l);
END;
INC (bytesWritten, l);
END WriteBuffered;
PROCEDURE MakeWriteBuffer (fHdl : fileHandle);
BEGIN
buffer := NIL;
bufSize := $80000;
WHILE (buffer = NIL) & (bufSize > 0) DO
buffer := MagicDOS.Malloc ( bufSize);
IF buffer = NIL THEN DEC(bufSize, $1000) END;
END;
PutzLog.putTime();
IF bufSize = 0
THEN
buffer := NIL;
PutzLog.WriteLine ('Zuwenig Speicher fr Writebuffer');
ELSE
bufHdl := fHdl;
PutzLog.WriteCard (bufSize);
PutzLog.WriteLine (' Bytes Writebuffer angelegt');
END;
bufPos := 0;
bytesWritten := 0;
END MakeWriteBuffer;
PROCEDURE CloseWriteBuffer (fHdl : fileHandle);
BEGIN
IF (bufSize > 0) & (bufPos > 0) & (buffer # NIL) & (fHdl = bufHdl)
THEN
(* Buffer noch flushen *)
IF ~stopDelete THEN WriteBytes (fHdl, buffer, bufPos) END;
v.bool := MFree (buffer);
buffer := NIL;
bufPos := 0;
END;
END CloseWriteBuffer;
PROCEDURE getGroupMsgs() : LONGCARD;
BEGIN
RETURN (FileSize(parFile)- dataSys.dbHeaderLength) DIV TSIZE(dataSys.pBlock);
END getGroupMsgs;
PROCEDURE getGroupBytes() : LONGCARD;
BEGIN
RETURN FileSize (datFile);
END getGroupBytes;
(* Lsch-Funktionen *)
PROCEDURE GetDat (f : fileHandle; start : LONGCARD; buf : ADDRESS;
length : LONGCARD; VAR bytesRead : LONGCARD);
VAR sAddr : ADDRESS;
BEGIN
IF (start < datSize) &
(start + length <= datSize)
THEN
IF datBuffered
THEN
sAddr := datBuffer+ADDRESS(start);
Block.Copy (sAddr, length, buf);
bytesRead := length;
ELSE
start := MagicDOS.Fseek (start, f, MagicDOS.SeekStart);
ReadBytes (f, buf, length, bytesRead);
END;
ELSE
bytesRead := 0;
END;
END GetDat;
PROCEDURE CopyTab (index : CARDINAL);
VAR theCrc : CARDINAL;
bytesRead: LONGCARD;
BEGIN
IF tabBuffered
THEN
newTabArray^[msgCounter] := tabArray^[index];
ELSE
v.lcard := MagicDOS.Fseek (LONG(index)*2L, tabFile, MagicDOS.SeekStart);
ReadBytes (tabFile, ADR(theCrc), 2, bytesRead);
WriteBytes (newTab, ADR(theCrc), 2);
END;
END CopyTab;
PROCEDURE CopyParam (VAR param : dataSys.pBlock);
BEGIN
(* Neue CRC berechnen *)
param.crc := ZCalcCrc.CalcCrcArray(ADR(param)+ADDRESS(2), SHORT(TSIZE(dataSys.pBlock))-2);
IF parBuffered
THEN
newParArray^.params[msgCounter] := param;
ELSE
WriteBytes (newPar, ADR(param), TSIZE(dataSys.pBlock));
END;
END CopyParam;
PROCEDURE partDelete (idx : CARDINAL; VAR param : dataSys.pBlock);
VAR oldNum : CARDINAL;
newStart : LONGCARD;
dupeInfo : dataSys.dupeInfoType;
BEGIN
WITH param DO
(* Erst mal auf gltige Werte prfen *)
IF (Start < datSize) &
(hLength < 4096) &
(idLength < 1024) &
(Start+LONG(hLength)+LONG(Length) <= datSize)
THEN
oldNum := idx;
newNums[idx] := msgCounter;
IF ~(dataSys.bGelesen IN bits)
THEN
IF (firstUnread = dataSys.empty)
THEN
firstUnread := msgCounter;
END;
INC (unreadCounter);
END;
(* Kopieren der einzelnen Datei-Teile *)
(* zuerst TAB-Datei *)
CopyTab (oldNum);
IF stopDelete THEN RETURN END;
(* Jetzt DAT-Datei kopieren *)
GetDat (datFile, Start, buf, LONG(hLength)+LONG(Length), bRead);
IF bRead # LONG(hLength) + LONG(Length)
THEN
stopDelete := TRUE;
END;
GetDat (datFile, Start + LONG(hLength) + LONG(Length), ADR(dupeInfo), TSIZE(dataSys.dupeInfoType), bRead);
IF bRead # TSIZE (dataSys.dupeInfoType)
THEN
stopDelete := TRUE;
END;
newStart := FilePos (newDat);
(* Redundaten Infos anpassen *)
dupeInfo.Datum := Datum;
dupeInfo.items := items;
dupeInfo.bits := bits;
dupeInfo.hLength := hLength;
dupeInfo.idLength := idLength;
dupeInfo.Start := newStart;
dupeInfo.setTerminator := dataSys.Terminator;
IF Length > LENGTH (deletedText)
THEN
Length := LENGTH (deletedText);
dupeInfo.Length := Length;
WriteBuffered (newDat, buf, hLength);
IF stopDelete THEN RETURN END;
WriteBuffered (newDat, CADR(deletedText), Length);
IF stopDelete THEN RETURN END;
WriteBuffered (newDat, ADR(dupeInfo), TSIZE(dataSys.dupeInfoType));
IF stopDelete THEN RETURN END;
ELSE
dupeInfo.Length := Length;
WriteBuffered (newDat, buf, LONG(hLength)+LONG(Length));
IF stopDelete THEN RETURN END;
WriteBuffered (newDat, ADR(dupeInfo), TSIZE(dataSys.dupeInfoType));
IF stopDelete THEN RETURN END;
END;
(* Und jetzt noch PAR-Datei *)
Start := newStart;
KomCount := 0;
CopyParam(param);
INC(msgCounter);
INC(partDeleted);
ELSE
newNums[idx] := dataSys.notSaved;
INC (badMsg);
END;
END;
END partDelete;
PROCEDURE noDelete (idx : CARDINAL; VAR param : dataSys.pBlock);
VAR oldNum : CARDINAL;
newStart : LONGCARD;
dupeInfo : dataSys.dupeInfoType;
BEGIN
WITH param DO
(* Erst mal auf gltige Werte prfen *)
IF (Start < datSize) &
(hLength < 4096) &
(idLength < 1024) &
(Start+LONG(hLength)+LONG(Length) <= datSize)
THEN
oldNum := idx;
newNums[idx] := msgCounter;
IF ~(dataSys.bGelesen IN bits)
THEN
IF (firstUnread = dataSys.empty)
THEN
firstUnread := msgCounter;
END;
INC (unreadCounter);
END;
(* Kopieren der einzelnen Datei-Teile *)
(* zuerst TAB-Datei *)
CopyTab (oldNum);
IF stopDelete THEN RETURN END;
(* Jetzt DAT-Datei kopieren *)
GetDat (datFile, Start, buf, LONG(hLength)+LONG(Length), bRead);
IF bRead # LONG(hLength) + LONG(Length)
THEN
stopDelete := TRUE;
END;
GetDat (datFile, Start + LONG(hLength) + LONG(Length), ADR(dupeInfo), TSIZE(dataSys.dupeInfoType), bRead);
IF bRead # TSIZE (dataSys.dupeInfoType)
THEN
stopDelete := TRUE;
END;
newStart := FilePos (newDat);
(* redundante Infos anpassen *)
dupeInfo.Datum := Datum;
dupeInfo.items := items;
dupeInfo.bits := bits;
dupeInfo.hLength := hLength;
dupeInfo.idLength := idLength;
dupeInfo.Length := Length;
dupeInfo.Start := newStart;
dupeInfo.setTerminator := dataSys.Terminator;
WriteBuffered (newDat, buf, LONG(hLength)+LONG(Length));
IF stopDelete THEN RETURN END;
WriteBuffered (newDat, ADR(dupeInfo), TSIZE(dataSys.dupeInfoType));
IF stopDelete THEN RETURN END;
(* Und jetzt noch PAR-Datei *)
Start := newStart;
KomCount := 0;
CopyParam (param);
INC(msgCounter);
ELSE
newNums[idx] := dataSys.notSaved;
INC (badMsg);
END;
END;
END noDelete;
PROCEDURE totalDelete (idx : CARDINAL; VAR param : dataSys.pBlock);
BEGIN
newNums[idx] := dataSys.notSaved;
INC (deleted);
END totalDelete;
PROCEDURE badDelete (idx : CARDINAL; VAR param : dataSys.pBlock);
BEGIN
newNums[idx] := dataSys.notSaved;
INC (badMsg);
END badDelete;
PROCEDURE buildName (number: INTEGER; VAR gName : ARRAY OF CHAR);
BEGIN
IF number # dataSys.private
THEN
IF number <= 100
THEN
Strings.Concat ('gruppe', StrConv.NumToStr(number-1,10,2,'0'), gName, v.bool);
ELSE
Strings.Concat ('grupp', StrConv.NumToStr(number-1,10,3,'0'), gName, v.bool);
END;
ELSE
Strings.Assign ('private', gName,v.bool);
END;
END buildName;
PROCEDURE openGroup;
VAR datName,
tabName,
parName : ARRAY [0..255] OF CHAR;
gName : ARRAY [0..255] OF CHAR;
bRead : LONGCARD;
fHeader : dataSys.FileHeaderType;
BEGIN
buildName (currentGroup, gName);
Strings.Concat (MTPaths.DataPath, gName, datName, v.bool);
Strings.Assign (datName, parName, v.bool);
Strings.Assign (datName, tabName, v.bool);
Strings.Append ('.par',parName, v.bool);
Strings.Append ('.dat',datName, v.bool);
Strings.Append ('.tab',tabName, v.bool);
OpenFile (parFile, parName);
OpenFile (tabFile, tabName);
OpenFile (datFile, datName);
IF (parFile < 0) OR (tabFile < 0) OR (datFile < 0)
THEN
v.int := mtAlerts.Alert (1,"[3][CATPUTZ:|Die Gruppe kann|nicht geffnet werden!][[Abbruch]");
stopDelete := TRUE;
RETURN
END;
ReadBytes (parFile, ADR (fHeader), SIZE(fHeader), bRead);
IF (fHeader.CatMagic # dataSys.standardHeader.CatMagic) OR
(fHeader.Version # dataSys.standardHeader.Version) OR
(fHeader.VersionMagic # dataSys.standardHeader.VersionMagic)
THEN
v.int := mtAlerts.Alert (1, "[3][CATPUTZ:|Keine oder kaputte |CAT-Datenbank! |Header nicht in Ordnung!][[Abbruch]");
stopDelete := TRUE;
END;
v.lcard := MagicDOS.Fseek (0L, parFile, MagicDOS.SeekStart);
END openGroup;
PROCEDURE closeGroup;
BEGIN
v.int := MagicDOS.Fclose (parFile);
v.int := MagicDOS.Fclose (datFile);
v.int := MagicDOS.Fclose (tabFile);
END closeGroup;
PROCEDURE createNewFiles ();
VAR datName,
tabName,
parName : ARRAY [0..255] OF CHAR;
gName : ARRAY [0..255] OF CHAR;
BEGIN
buildName (currentGroup, gName);
Strings.Concat (PutzTypes.tmpPath, gName, datName, v.bool);
Strings.Assign (datName, parName, v.bool);
Strings.Assign (datName, tabName, v.bool);
Strings.Append ('.pa',parName, v.bool);
Strings.Append ('.da',datName, v.bool);
Strings.Append ('.ta',tabName, v.bool);
CreateFile (newPar, parName);
CreateFile (newTab, tabName);
CreateFile (newDat, datName);
IF (newPar < 0) OR (newTab < 0) OR (newDat < 0)
THEN
v.int := mtAlerts.Alert (1,"[3][CATPUTZ:|Kann temporre Dateien|nicht anlegen!][[Abbruch]");
stopDelete := TRUE;
END;
END createNewFiles;
PROCEDURE deleteNewFiles ();
VAR datName,
tabName,
parName : ARRAY [0..255] OF CHAR;
gName : ARRAY [0..255] OF CHAR;
res : INTEGER;
BEGIN
buildName (currentGroup, gName);
Strings.Concat (PutzTypes.tmpPath, gName, datName, v.bool);
Strings.Assign (datName, parName, v.bool);
Strings.Assign (datName, tabName, v.bool);
Strings.Append ('.pa', parName, v.bool);
Strings.Append ('.da', datName, v.bool);
Strings.Append ('.ta', tabName, v.bool);
v.bool := MagicDOS.Fdelete (parName);
v.bool := MagicDOS.Fdelete (tabName);
v.bool := MagicDOS.Fdelete (datName);
END deleteNewFiles;
PROCEDURE move (REF from, to : ARRAY OF CHAR; res :INTEGER);
VAR s, d : fileHandle;
mbuf : ADDRESS;
slen : LONGCARD;
blen : LONGCARD;
pos : LONGCARD;
readB: LONGCARD;
PROCEDURE closeIt();
BEGIN
v.bool := MFree (mbuf);
v.int := MagicDOS.Fclose (d);
v.int := MagicDOS.Fclose (s);
END closeIt;
BEGIN
OpenFile (s, from);
CreateFile (d, to);
slen := FileSize (s);
blen := MemAvail();
IF blen < 12000 THEN RETURN END;
blen := blen - 8192;
mbuf := MagicDOS.Malloc ( blen);
IF mbuf = NIL THEN RETURN END;
pos := 0L;
WHILE pos + blen <= slen DO
ReadBytes (s, mbuf, blen, readB);
IF stopDelete
THEN
closeIt;
RETURN
END;
WriteBytes (d, mbuf, blen);
IF stopDelete
THEN
closeIt;
RETURN
END;
INC (pos, blen);
END;
IF pos < slen THEN
ReadBytes (s, mbuf, slen-pos, readB);
IF stopDelete
THEN
closeIt;
RETURN
END;
WriteBytes (d, mbuf, slen-pos);
IF stopDelete
THEN
closeIt;
RETURN
END;
END;
closeIt;
v.bool := MagicDOS.Fdelete (from);
END move;
PROCEDURE makeNewNames ();
VAR ndatName,
ntabName,
nparName,
datName,
tabName,
parName : ARRAY [0..255] OF CHAR;
gName : ARRAY [0..255] OF CHAR;
res : INTEGER;
BEGIN
buildName (currentGroup, gName);
Strings.Concat (MTPaths.DataPath, gName, datName, v.bool);
Strings.Assign (datName, parName, v.bool);
Strings.Assign (datName, tabName, v.bool);
Strings.Concat (PutzTypes.tmpPath, gName, ndatName, v.bool);
Strings.Assign (ndatName, nparName, v.bool);
Strings.Assign (ndatName, ntabName, v.bool);
Strings.Append ('.par', parName, v.bool);
Strings.Append ('.dat', datName, v.bool);
Strings.Append ('.tab', tabName, v.bool);
Strings.Append ('.pa', nparName, v.bool);
Strings.Append ('.da', ndatName, v.bool);
Strings.Append ('.ta', ntabName, v.bool);
v.bool := MagicDOS.Fdelete (parName);
v.bool := MagicDOS.Fdelete (datName);
v.bool := MagicDOS.Fdelete (tabName);
res := MagicDOS.Frename (nparName, parName);
IF res # 0
THEN
move (ndatName, datName, res);
move (nparName, parName, res);
move (ntabName, tabName, res);
ELSE
res := MagicDOS.Frename (ndatName, datName);
res := MagicDOS.Frename (ntabName, tabName);
END;
END makeNewNames;
PROCEDURE openNewPar();
VAR parName : ARRAY [0..255] OF CHAR;
gName : ARRAY [0..255] OF CHAR;
BEGIN
buildName (currentGroup, gName);
Strings.Concat (PutzTypes.tmpPath, gName, parName, v.bool);
Strings.Append ('.PA',parName, v.bool);
OpenFile (newPar, parName);
END openNewPar;
PROCEDURE BufferTabAndPar();
VAR tabSize, parSize : LONGCARD;
memS : LONGCARD;
BEGIN
(* zuerst PAR buffern *)
parArray := NIL;
newParArray := NIL;
tabArray := NIL;
newTabArray := NIL;
parSize := FileSize (parFile);
IF parSize > 1
THEN
AnzMessages := SHORT((parSize - dataSys.dbHeaderLength) DIV TSIZE(dataSys.pBlock));
ELSE
AnzMessages := 0;
END;
memS := MemAvail();
IF (memS < 8192) OR (memS-8192L < 2L*parSize)
THEN
parBuffered := FALSE;
tabBuffered := FALSE;
RETURN
END;
parArray := MagicDOS.Malloc (parSize);
newParArray := MagicDOS.Malloc (parSize);
IF (parArray= NIL) OR (newParArray = NIL)
THEN
IF parArray # NIL THEN v.bool := MFree (parArray) END;
IF newParArray # NIL THEN v.bool := MFree (newParArray) END;
parBuffered := FALSE;
tabBuffered := FALSE;
RETURN
END;
ReadBytes (parFile, parArray, parSize, bRead);
IF bRead = parSize
THEN
parBuffered := TRUE;
newParArray^.dbHeader := parArray^.dbHeader;
ELSE
parBuffered := FALSE;
tabBuffered := FALSE;
IF parArray # NIL THEN v.bool := MFree (parArray) END;
IF newParArray # NIL THEN v.bool := MFree (newParArray) END;
END;
(* jetzt TAB puffern *)
tabSize := FileSize (tabFile);
memS := MemAvail();
IF (memS < 8192) OR (memS-8192L < 2L*tabSize) (* 2-mal fr alt- und neu *)
THEN
tabBuffered := FALSE;
RETURN
END;
tabArray := MagicDOS.Malloc (tabSize);
newTabArray := MagicDOS.Malloc (tabSize);
IF (tabArray = NIL) OR (newTabArray = NIL)
THEN
IF tabArray # NIL THEN v.bool := MFree (tabArray) END;
IF newTabArray # NIL THEN v.bool := MFree (newTabArray) END;
tabBuffered := FALSE;
RETURN
END;
ReadBytes (tabFile, tabArray, tabSize, bRead);
IF bRead = tabSize THEN tabBuffered := TRUE
ELSE tabBuffered := FALSE;
IF tabArray # NIL THEN v.bool := MFree (tabArray) END;
IF newTabArray # NIL THEN v.bool := MFree (newTabArray) END;
END;
END BufferTabAndPar;
PROCEDURE BufferDatFile();
VAR memS : LONGCARD;
BEGIN
(* zuerst TAB buffern *)
datSize := FileSize (datFile);
datBuffer := NIL;
memS := MemAvail();
IF (memS < 8192) OR (memS-8192L < datSize)
THEN
datBuffered := FALSE;
RETURN
END;
datBuffer := MagicDOS.Malloc (datSize);
IF datBuffer = NIL
THEN
datBuffered := FALSE;
RETURN
END;
ReadBytes (datFile, datBuffer, datSize, bRead);
IF bRead = datSize THEN datBuffered := TRUE
ELSE datBuffered := FALSE; v.bool := MFree (datBuffer); END;
END BufferDatFile;
PROCEDURE killBuffer();
BEGIN
IF datBuffer # NIL THEN v.bool := MFree (datBuffer) END;
IF newTabArray # NIL THEN v.bool := MFree (newTabArray); END;
IF tabArray # NIL THEN v.bool := MFree (tabArray); END;
IF newParArray # NIL THEN v.bool := MFree (newParArray); END;
IF parArray # NIL THEN v.bool := MFree (parArray); END;
END killBuffer;
PROCEDURE GetParam (pFile : fileHandle; index : CARDINAL;
parArray : PutzTypes.parFilePtr; VAR param: dataSys.pBlock);
BEGIN
IF parBuffered
THEN
param := parArray^.params[index]
ELSE
v.lcard := MagicDOS.Fseek (dataSys.dbHeaderLength+LONG(index)*TSIZE(dataSys.pBlock), pFile, MagicDOS.SeekStart);
ReadBytes (pFile, ADR(param), TSIZE (dataSys.pBlock), v.lcard);
END;
END GetParam;
PROCEDURE PutParam (pFile : fileHandle; index : CARDINAL;
parArray : PutzTypes.parFilePtr; VAR param : dataSys.pBlock);
BEGIN
param.crc := ZCalcCrc.CalcCrcArray(ADR(param)+ADDRESS(2), SHORT(TSIZE(dataSys.pBlock))-2);
IF parBuffered
THEN
parArray^.params[index] := param;
ELSE
v.lcard := MagicDOS.Fseek (dataSys.dbHeaderLength+LONG(index)*TSIZE(dataSys.pBlock), pFile, MagicDOS.SeekStart);
WriteBytes (pFile, ADR(param), TSIZE(dataSys.pBlock));
END;
END PutParam;
PROCEDURE CheckLongDate (date : LONGCARD) : BOOLEAN;
(* Cat-Datum in ein menschenlesbares verwandeln *)
VAR c1, year, y,m,d : CARDINAL;
BEGIN
(* Jahr *)
year:= SHORT(date DIV 100000000);
date:= date MOD 100000000;
INC(year, 1990);
(* Jetzt ist das Jahr bestimmt. *)
IF (year < 1980)
THEN
RETURN FALSE
END;
y := year;
(* Monat *)
c1 := SHORT(date DIV 10000000);
m := c1 * 10;
date:= date MOD 10000000;
c1 := SHORT(date DIV 1000000);
m := m + c1;
IF (m < 1) OR (m > 12) THEN RETURN FALSE END;
date:= date MOD 1000000;
(* Tag *)
c1 := SHORT(date DIV 100000);
d := c1 * 10;
date:= date MOD 100000;
c1 := SHORT(date DIV 10000);
d := d + c1;
IF (d < 1) OR (d > 31) THEN RETURN FALSE END;
date:= date MOD 10000;
(* Stunde *)
c1 := SHORT(date DIV 1000);
date:= date MOD 1000;
m := c1;
c1 := SHORT(date DIV 100);
m := m*10 + c1; (* Stunde *)
IF m > 23 THEN RETURN FALSE END;
date:= date MOD 100;
(* Minute *)
c1 := SHORT(date DIV 10);
date:= date MOD 10;
m := c1*10 + SHORT(date);
IF m > 59 THEN RETURN FALSE END;
RETURN TRUE;
END CheckLongDate;
PROCEDURE IsMessOk (VAR param: dataSys.pBlock): BOOLEAN;
BEGIN
RETURN (param.Start < datSize) &
(param.hLength < 4096) &
(param.idLength < 1024) &
(param.Start+LONG(param.hLength)+LONG(param.Length) <= datSize) &
CheckLongDate (param.Datum);
END IsMessOk;
PROCEDURE deleteByFlags (VAR param : dataSys.pBlock; idx: CARDINAL; pass: INTEGER) : delState;
VAR pInfo : dataSys.pInfoType;
br : LONGCARD;
BEGIN
WITH putzOpts DO
(* Erst mal auf gltige Werte prfen *)
IF IsMessOk (param)
THEN
(* Hier mu jetzt nur bei der privaten Gruppe auch noch das
* Statusdatum geprft werden
*)
IF currentGroup = dataSys.private
THEN
GetDat (datFile, param.Start+LONG(param.hLength) - TSIZE (dataSys.pInfoType), ADR(pInfo), TSIZE(dataSys.pInfoType), br);
IF ~CheckLongDate (pInfo.LeseDatum)
THEN
RETURN badMess
END;
IF (pInfo.Status = 'Z') OR (pInfo.Status = 'N')
THEN
IF dataSys.bTotalloeschung IN param.bits
THEN RETURN totalDel
ELSIF dataSys.bTeilloeschung IN param.bits
THEN
IF (param.KomCount = 0) & delWithoutComm
THEN
RETURN totalDel
ELSE
RETURN partDel
END;
END;
RETURN noDel;
END;
END;
IF ((intFlag = noDel) & (dataSys.bInteressant IN param.bits)) OR
((usrFlg1 = noDel) & (dataSys.bUser1 IN param.bits) ) OR
((usrFlg2 = noDel) & (dataSys.bUser2 IN param.bits) ) OR
((filtFlg = noDel) & (dataSys.bFiltered IN param.bits) ) OR
((readFlg = noDel) & (dataSys.bGelesen IN param.bits) )
THEN
RETURN noDel
END;
IF dataSys.bTotalloeschung IN param.bits
THEN RETURN totalDel
ELSIF dataSys.bTeilloeschung IN param.bits
THEN
IF (param.KomCount = 0) & delWithoutComm
THEN
RETURN totalDel
ELSE
RETURN partDel
END;
END;
IF deleteByDate & (param.Datum > delDate)
THEN
RETURN noDel
END;
IF ((intFlag = totalDel) & (dataSys.bInteressant IN param.bits)) OR
((usrFlg1 = totalDel) & (dataSys.bUser1 IN param.bits) ) OR
((usrFlg2 = totalDel) & (dataSys.bUser2 IN param.bits) ) OR
((filtFlg = totalDel) & (dataSys.bFiltered IN param.bits) ) OR
((readFlg = totalDel) & (dataSys.bGelesen IN param.bits) )
THEN
RETURN totalDel
END;
IF ((intFlag = partDel) & (dataSys.bInteressant IN param.bits)) OR
((usrFlg1 = partDel) & (dataSys.bUser1 IN param.bits) ) OR
((usrFlg2 = partDel) & (dataSys.bUser2 IN param.bits) ) OR
((filtFlg = partDel) & (dataSys.bFiltered IN param.bits) ) OR
((readFlg = partDel) & (dataSys.bGelesen IN param.bits) )
THEN
IF (param.KomCount = 0)
THEN
RETURN totalDel
ELSE
RETURN partDel
END;
END;
ELSE
RETURN badMess
END;
END;
IF (putzOpts.noRdFlg # ignoreFlag) & ~(dataSys.bGelesen IN param.bits)
THEN
RETURN putzOpts.noRdFlg
END;
RETURN noDel
END deleteByFlags;
PROCEDURE deleteDate (VAR param : dataSys.pBlock; idx: CARDINAL; pass: INTEGER) : delState;
VAR pInfo : dataSys.pInfoType;
br : LONGCARD;
BEGIN
WITH putzOpts DO
(* Erst mal auf gltige Werte prfen *)
IF IsMessOk (param)
THEN
(* Hier mu jetzt nur bei der privaten Gruppe auch noch das
* Statusdatum geprft werden
*)
IF currentGroup = dataSys.private
THEN
GetDat (datFile, param.Start+LONG(param.hLength) - TSIZE (dataSys.pInfoType), ADR(pInfo), TSIZE(dataSys.pInfoType), br);
IF ~CheckLongDate (pInfo.LeseDatum)
THEN
RETURN badMess
END;
IF (pInfo.Status = 'Z') OR (pInfo.Status = 'N')
THEN
IF dataSys.bTotalloeschung IN param.bits
THEN RETURN totalDel
ELSIF dataSys.bTeilloeschung IN param.bits
THEN
IF (param.KomCount = 0) & delWithoutComm
THEN
RETURN totalDel
ELSE
RETURN partDel
END;
END;
RETURN noDel;
END;
END;
IF deleteByDate & (param.Datum > delDate)
THEN
RETURN noDel
END;
IF (dataSys.bInteressant IN param.bits)
THEN
RETURN noDel
END;
RETURN totalDel
ELSE
RETURN badMess;
END;
END;
END deleteDate;
VAR newAnz,
minIdx : CARDINAL;
PROCEDURE deleteDateAndNum (VAR param : dataSys.pBlock; idx: CARDINAL; pass: INTEGER) : delState;
VAR pInfo : dataSys.pInfoType;
br : LONGCARD;
res : delState;
BEGIN
WITH putzOpts DO
(* Erst mal auf gltige Werte prfen *)
IF IsMessOk (param)
THEN
(* Hier mu jetzt nur bei der privaten Gruppe auch noch das
* Statusdatum geprft werden
*)
IF currentGroup = dataSys.private
THEN
GetDat (datFile, param.Start+LONG(param.hLength) - TSIZE (dataSys.pInfoType), ADR(pInfo), TSIZE(dataSys.pInfoType), br);
IF ~CheckLongDate (pInfo.LeseDatum)
THEN
RETURN badMess
END;
IF (pInfo.Status = 'Z') OR (pInfo.Status = 'N')
THEN
IF dataSys.bTotalloeschung IN param.bits
THEN RETURN totalDel
ELSIF dataSys.bTeilloeschung IN param.bits
THEN
IF (param.KomCount = 0) & delWithoutComm
THEN
RETURN totalDel
ELSE
RETURN partDel
END;
END;
RETURN noDel;
END;
END;
IF pass = 1
THEN
IF (param.Datum > delDate)
THEN
IF newAnz >= number
THEN
res := totalDel
ELSE
INC (newAnz);
res := noDel
END;
ELSE
res := totalDel
END;
IF (res = noDel)
THEN
minIdx := idx;
END;
ELSE (* pass > 1 *)
IF idx >= minIdx
THEN
IF (param.Datum > delDate)
THEN
RETURN noDel
ELSE
IF (dataSys.bInteressant IN param.bits)
THEN
RETURN noDel
END;
RETURN totalDel
END;
ELSE
IF (dataSys.bInteressant IN param.bits)
THEN
RETURN noDel
END;
RETURN totalDel
END;
END;
ELSE
RETURN badMess;
END;
END;
END deleteDateAndNum;
PROCEDURE deleteNum (VAR param : dataSys.pBlock; idx: CARDINAL; pass: INTEGER) : delState;
VAR pInfo : dataSys.pInfoType;
br : LONGCARD;
res : delState;
BEGIN
WITH putzOpts DO
(* Erst mal auf gltige Werte prfen *)
IF IsMessOk (param)
THEN
(* Hier mu jetzt nur bei der privaten Gruppe auch noch das
* Statusdatum geprft werden
*)
IF currentGroup = dataSys.private
THEN
GetDat (datFile, param.Start+LONG(param.hLength) - TSIZE (dataSys.pInfoType), ADR(pInfo), TSIZE(dataSys.pInfoType), br);
IF ~CheckLongDate (pInfo.LeseDatum)
THEN
RETURN badMess
END;
IF (pInfo.Status = 'Z') OR (pInfo.Status = 'N')
THEN
IF dataSys.bTotalloeschung IN param.bits
THEN RETURN totalDel
ELSIF dataSys.bTeilloeschung IN param.bits
THEN
IF (param.KomCount = 0) & delWithoutComm
THEN
RETURN totalDel
ELSE
RETURN partDel
END;
END;
RETURN noDel;
END;
END;
IF pass = 1
THEN
IF newAnz >= number
THEN
res := totalDel
ELSE
INC (newAnz);
res := noDel
END;
IF (res = noDel)
THEN
minIdx := idx;
END;
ELSE (* pass > 1 *)
IF idx >= minIdx
THEN
RETURN noDel
ELSE
IF (dataSys.bInteressant IN param.bits)
THEN
RETURN noDel
END;
RETURN totalDel
END;
END;
ELSE
RETURN badMess;
END;
END;
END deleteNum;
VAR shouldBeDeleted : PutzTypes.deleteProc;
PROCEDURE doDelete(): INTEGER;
VAR i : CARDINAL;
dState : delState;
param : dataSys.pBlock;
pass : INTEGER;
doPass2 : BOOLEAN;
BEGIN
doPass2 := FALSE;
pass := 0;
IF (putzOpts.dMode = PutzTypes.dNum) OR (putzOpts.dMode = PutzTypes.dDateAndNum)
THEN
(* First pass! *)
pass := 1;
newAnz := 0;
minIdx := AnzMessages;
FOR i := AnzMessages-1 TO 0 BY -1 DO
GetParam (parFile, i, parArray, param);
IF ~PutzAction.TellAction (4, AnzMessages-i) THEN stopDelete := TRUE; RETURN 0 END;
dState := shouldBeDeleted (param, i, pass);
IF dState = badMess
THEN
doPass2 := TRUE;
END;
END;
PutzLog.putTime();
PutzLog.WriteString ('Pass 1 beendet');
PutzLog.WriteLn;
IF (putzOpts.dMode = PutzTypes.dNum) & ~doPass2
THEN
IF putzOpts.number >= AnzMessages -1 THEN
PutzLog.putTime();
PutzLog.WriteString ('Pass 2 wird nicht bentigt, nichts zu lschen');
PutzLog.WriteLn;
RETURN 1
END;
END;
ELSE
PutzLog.putTime();
PutzLog.WriteString ('Pass 1 wird nicht bentigt, bersprungen');
PutzLog.WriteLn;
END;
INC (pass);
PutzAction.BeginNextPass(1);
FOR i := 0 TO AnzMessages-1 DO
GetParam (parFile, i, parArray, param);
IF ~PutzAction.TellAction (1, i+1) THEN stopDelete := TRUE; RETURN 0 END;
IF (i = AnzMessages-1) & (msgCounter = 0)
THEN
dState := noDel
ELSE
dState := shouldBeDeleted (param, i, pass);
END;
CASE dState OF
partDel : partDelete (i, param); |
noDel : noDelete (i, param); |
totalDel: totalDelete (i, param); |
badMess : badDelete (i, param); |
ELSE
END;
IF stopDelete THEN RETURN 0 END;
(*
PutParam (parFile, i, parArray, param);
*)
END;
PutzLog.putTime();
PutzLog.WriteString ('Pass 2 beendet');
PutzLog.WriteLn;
RETURN 0
END doDelete;
PROCEDURE FlushParam(pFile : fileHandle; addr : ADDRESS);
BEGIN
IF parBuffered
THEN
v.lcard := MagicDOS.Fseek (0L, pFile, MagicDOS.SeekStart);
WriteBytes (pFile, addr, dataSys.dbHeaderLength + (LONG(msgCounter)*TSIZE(dataSys.pBlock)));
END;
END FlushParam;
PROCEDURE FlushTab (pFile : fileHandle; addr : ADDRESS);
BEGIN
IF tabBuffered
THEN
v.lcard := MagicDOS.Fseek (0L, pFile, MagicDOS.SeekStart);
WriteBytes (pFile, addr,
LONG(msgCounter)*TSIZE(CARDINAL));
END;
END FlushTab;
PROCEDURE bufferNewPar;
VAR parSize : LONGCARD;
memS : LONGCARD;
BEGIN
AnzMessages := msgCounter;
parSize := (LONG(AnzMessages) * TSIZE (dataSys.pBlock)) + dataSys.dbHeaderLength;
IF parBuffered
THEN
Block.Copy (newParArray, parSize, parArray);
v.bool := MFree (newParArray);
ELSE
parArray := NIL;
memS := MemAvail();
IF (memS < 8192) OR (memS-8192L < parSize)
THEN
parBuffered := FALSE;
RETURN
END;
parArray := MagicDOS.Malloc (parSize);
IF parArray = NIL
THEN
parBuffered := FALSE;
RETURN
END;
v.lcard := MagicDOS.Fseek (0L, newPar, MagicDOS.SeekStart);
ReadBytes (newPar, parArray, parSize, bRead);
IF bRead = parSize THEN parBuffered := TRUE
ELSE parBuffered := FALSE; v.bool := MFree (parArray); END;
END;
END bufferNewPar;
PROCEDURE buildNewRight(pFile : fileHandle; index, comment : CARDINAL;
parArray : PutzTypes.parFilePtr) : CARDINAL;
VAR param, pdown : dataSys.pBlock;
run : CARDINAL;
BEGIN
GetParam (pFile, index, parArray, param);
run := param.downMess;
IF run = comment THEN RETURN dataSys.empty END;
LOOP
GetParam (pFile, run, parArray, pdown);
IF pdown.rightMess = comment THEN RETURN run END;
IF (pdown.rightMess = dataSys.empty) OR (pdown.rightMess = dataSys.notSaved)
THEN
pdown.rightMess := comment;
PutParam (pFile, run, parArray, pdown);
RETURN run
ELSE
run := pdown.rightMess;
END;
END;
END buildNewRight;
PROCEDURE IncCommCount(pFile : fileHandle; index, comment : CARDINAL;
parArray : PutzTypes.parFilePtr);
VAR param : dataSys.pBlock;
BEGIN
GetParam (pFile, index, parArray, param);
INC (param.KomCount);
IF param.KomCount = 1
THEN
param.downMess := comment;
IF param.downMess = dataSys.notSaved THEN
param.downMess := dataSys.empty; param.KomCount := 0
END;
END;
PutParam (pFile, index, parArray, param);
END IncCommCount;
PROCEDURE linkNewPar;
VAR i : CARDINAL;
param : dataSys.pBlock;
par2 : dataSys.pBlock;
par3 : dataSys.pBlock;
par2Idx: CARDINAL;
PROCEDURE makeNewLinks();
VAR i : CARDINAL;
BEGIN
FOR i := 0 TO AnzMessages-1 DO
GetParam (newPar, i, parArray, param);
WITH param DO
(*
IF currentGroup # dataSys.private
THEN
*)
(* Kommentare bearbeiten *)
IF (upMess < dataSys.notSaved)
THEN
upMess := newNums[upMess];
IF (upMess # dataSys.notSaved) & (upMess >= i) THEN upMess := dataSys.notSaved END;
IF (upMess < dataSys.notSaved) & (upMess < AnzMessages)
THEN
IncCommCount (newPar, upMess, i, parArray);
END;
END;
IF (downMess < dataSys.notSaved)
THEN
downMess := newNums[downMess];
IF (downMess # dataSys.notSaved) & ((downMess <= i) OR (downMess >= AnzMessages)) THEN downMess := dataSys.notSaved END;
END;
IF (downMess = dataSys.notSaved) OR (downMess > AnzMessages) THEN downMess := dataSys.empty; KomCount := 0 END;
IF (rightMess < dataSys.notSaved)
THEN
rightMess := newNums[rightMess];
IF (rightMess # dataSys.notSaved) & ((rightMess >= i) OR (rightMess >= AnzMessages)) THEN rightMess := dataSys.notSaved END;
END;
IF rightMess = dataSys.notSaved THEN rightMess := dataSys.empty END;
IF leftMess < dataSys.notSaved
THEN
leftMess := newNums[leftMess];
IF (leftMess # dataSys.notSaved) & ((leftMess <= i) OR (leftMess >= AnzMessages)) THEN leftMess := dataSys.notSaved END;
IF (leftMess = dataSys.notSaved) & (upMess < dataSys.notSaved) & (upMess < AnzMessages)
THEN
leftMess := buildNewRight (newPar, upMess, i, parArray);
END;
END;
IF (leftMess = dataSys.notSaved) OR (leftMess >= AnzMessages) THEN leftMess := dataSys.empty END;
(*
ELSE
IF Question < dataSys.notSaved
THEN
Question := newNums[Question];
IF (Question # dataSys.notSaved) & (Question >=i) THEN Question := dataSys.notSaved END;
END;
IF Answer < dataSys.notSaved
THEN
Answer := newNums[Answer];
IF (Answer # dataSys.notSaved) & (Answer <= i) THEN Answer := dataSys.notSaved END;
END;
IF Answer = dataSys.notSaved THEN Answer := dataSys.empty END;
END;
*)
END (* with param *);
PutParam (newPar, i, parArray, param);
END (* FOR i *);
END makeNewLinks;
PROCEDURE checkLinks();
VAR i : CARDINAL;
BEGIN
FOR i := 0 TO AnzMessages-1 DO
GetParam (newPar, i, parArray, param);
WITH param DO
KomCount := 0; (* Wird gleich wieder neu aufgebaut! *)
(* Check down messages and correct errors *)
IF downMess < dataSys.notSaved
THEN
GetParam (newPar, downMess, parArray, par2);
IF par2.upMess # i
THEN
(* Error in ParBlock! *)
par2.upMess := i;
PutParam (newPar, downMess, parArray, par2);
END;
par2Idx := downMess;
WHILE par2.rightMess < dataSys.notSaved DO
GetParam (newPar, par2.rightMess, parArray, par3);
IF par3.upMess # i
THEN
(* Error in ParBlock! *)
par3.upMess := i;
PutParam (newPar, downMess, parArray, par3);
END;
(* Check left-right *)
IF par3.leftMess # par2Idx
THEN
(* Error in ParBlock! *)
par3.leftMess := par2Idx;
PutParam (newPar, downMess, parArray, par3);
END;
par2Idx := par2.rightMess;
par2 := par3;
END;
END;
IF (upMess < dataSys.notSaved) & (upMess < AnzMessages)
THEN
IncCommCount (newPar, upMess, i, parArray);
END;
END;
PutParam (newPar, i, parArray, param);
END;
END checkLinks;
BEGIN
openNewPar();
bufferNewPar;
IF AnzMessages > 0 THEN
(* Neue Verkettung aufbauen *)
makeNewLinks();
(* So, und jetzt noch mal alles berprfen *)
checkLinks ();
END;
IF parBuffered THEN FlushParam(newPar, parArray); v.bool := MFree (parArray); END;
END linkNewPar;
(*
TYPE posType = (aktuellePos, neuePos, letztePos, unreadPos, unreadCount);
TYPE PositionType = (actualPos, newPos, lastPos);
*)
CONST maxGroup = 255;
TYPE GrArray = ARRAY[0..maxGroup] OF dataSys.onePos;
GrPosType = RECORD
hdr : dataSys.FileHeaderType;
pos : GrArray;
END;
VAR grPos : GrPosType;
newPos: dataSys.grPosType;
PROCEDURE CreatePosArray (used: CARDINAL): BOOLEAN;
VAR i : CARDINAL;
z : dataSys.posType;
BEGIN
newPos.usedGroups := used;
newPos.posGroups := newPos.usedGroups;
IF newPos.posGroups < dataSys.maxGroup - 50
THEN
INC (newPos.posGroups, 50);
ELSE
newPos.posGroups := dataSys.maxGroup;
END;
(* Jetzt Speicher allozieren *)
Storage.ALLOCATE (newPos.pos, LONG(newPos.posGroups) * TSIZE (dataSys.onePos));
IF newPos.pos = NIL THEN
newPos.usedGroups := 0;
newPos.posGroups := 0;
RETURN FALSE
END;
FOR i := 0 TO newPos.posGroups -1 DO
FOR z := aktuellePos TO unreadCount DO
newPos.pos^[i, z] := dataSys.empty
END;
END;
RETURN TRUE;
END CreatePosArray;
PROCEDURE GetOnePos (group: CARDINAL; subIdx: dataSys.posType): CARDINAL;
BEGIN
IF group < newPos.usedGroups
THEN
RETURN newPos.pos^[group, subIdx]
END;
RETURN dataSys.empty;
END GetOnePos;
PROCEDURE SetOnePos (group: CARDINAL; subIdx: dataSys.posType; value: CARDINAL);
VAR newSize : CARDINAL;
newArray: POINTER TO ARRAY [0..dataSys.maxGroup] OF dataSys.onePos;
i : CARDINAL;
z : dataSys.posType;
BEGIN
IF group >= newPos.posGroups
THEN
(* Realloc, Array vergrern *)
IF newSize < dataSys.maxGroup - 20
THEN
newSize := group+20;
ELSE
newSize := dataSys.maxGroup;
END;
Storage.ALLOCATE (newArray, LONG(newSize) * TSIZE (dataSys.onePos));
IF newArray = NIL THEN RETURN END;
Block.Clear (newArray, LONG(newSize) * TSIZE (dataSys.onePos));
FOR i := newPos.posGroups TO newSize DO
FOR z := aktuellePos TO unreadCount DO
newPos.pos^[i, z] := dataSys.empty
END;
END;
Block.Copy (newPos.pos, LONG(newPos.posGroups) * TSIZE (dataSys.onePos), newArray);
Storage.DEALLOCATE (newPos.pos, 0);
newPos.posGroups := newSize;
newPos.pos := ADDRESS(newArray);
END;
newPos.usedGroups := BinOps.HigherCard (newPos.usedGroups, group);
newPos.pos^[group, subIdx] := value;
END SetOnePos;
PROCEDURE FreeGrPos ();
BEGIN
IF newPos.pos # NIL THEN
Storage.DEALLOCATE (newPos.pos, 0);
newPos.pos := NIL;
END;
END FreeGrPos;
PROCEDURE ReadGrPos (VAR isNew : BOOLEAN): BOOLEAN;
VAR parName : ARRAY [0..255] OF CHAR;
gName : ARRAY [0..255] OF CHAR;
grFile : fileHandle;
pos : CARDINAL;
voidLC : LONGCARD;
size : LONGCARD;
count : CARDINAL;
BEGIN
Strings.Assign ('gruppen.pos',gName, v.bool);
Strings.Concat (MTPaths.DataPath, gName, parName, v.bool);
OpenFile (grFile, parName);
IF grFile < 0
THEN
RETURN FALSE
END;
(* File ist jetzt offen *)
(* Erstmal Header lesen und sehen, welche Version wir haben *)
ReadBytes (grFile, ADR(grPos), dataSys.dbHeaderLength, voidLC);
(* Jetzt den Header testen *)
IF (grPos.hdr.CatMagic # dataSys.dbCatMagic) OR
(grPos.hdr.Version # dataSys.dbVersion) OR
((grPos.hdr.VersionMagic # dataSys.dbVersionMagic) &
(grPos.hdr.VersionMagic # dataSys.grPosVersionMagic))
THEN
(* damit knnen wir nichts anfangen, raus hier. *)
v.int := MagicDOS.Fclose (grFile);
RETURN FALSE
END;
(* Jetzt mal sehen, welche Version wir haben *)
IF grPos.hdr.VersionMagic = dataSys.dbVersionMagic
THEN
isNew := FALSE;
(* Alte Version, also alte Routine nehmen *)
voidLC := MagicDOS.Fseek (0, grFile, MagicDOS.SeekStart);
ReadBytes (grFile, ADR(grPos), SIZE(grPos), voidLC);
v.int := MagicDOS.Fclose (grFile);
ELSIF grPos.hdr.VersionMagic = dataSys.grPosVersionMagic
THEN
isNew := TRUE;
(* neue Version vom Gruppen.POS *)
(* Gre feststellen *)
size := FileSize (grFile);
v.lcard := MagicDOS.Fseek (0, grFile, MagicDOS.SeekStart);
count := SHORT((size-dataSys.dbHeaderLength) DIV TSIZE (dataSys.onePos));
DEC (count); (* Wegen save-Info *)
ReadBytes (grFile, ADR(newPos.head), dataSys.dbHeaderLength, voidLC);
ReadBytes (grFile, ADR(newPos.save), TSIZE(dataSys.onePos), voidLC);
(* Jetzt Speicher allozieren *)
IF ~CreatePosArray (count)
THEN
v.int := MagicDOS.Fclose (grFile);
RETURN FALSE
END;
ReadBytes (grFile, newPos.pos, LONG(count) * TSIZE(dataSys.onePos), voidLC);
(* Jetzt ist alles gelesen, wieder schlieen *)
v.int := MagicDOS.Fclose (grFile);
ELSE
v.int := MagicDOS.Fclose (grFile);
RETURN FALSE;
END;
RETURN TRUE;
END ReadGrPos;
PROCEDURE WriteGrPos (new: BOOLEAN): BOOLEAN;
VAR parName : ARRAY [0..255] OF CHAR;
gName : ARRAY [0..255] OF CHAR;
grFile : fileHandle;
BEGIN
Strings.Assign ('gruppen.pos',gName, v.bool);
Strings.Concat (MTPaths.DataPath, gName, parName, v.bool);
CreateFile (grFile, parName);
IF grFile > 0
THEN
IF ~new
THEN
(* Altes Format speichern *)
WriteBytes (grFile, ADR(grPos), SIZE(grPos));
v.int := MagicDOS.Fclose (grFile);
ELSE
newPos.head := dataSys.standardHeader;
newPos.head.VersionMagic := dataSys.grPosVersionMagic;
(* Header schreiben *)
WriteBytes (grFile, ADR(newPos.head), dataSys.dbHeaderLength);
(* Save-Bereich schreiben *)
WriteBytes (grFile, ADR(newPos.save), TSIZE(dataSys.onePos));
(* Gruppenbereich schreiben *)
WriteBytes (grFile, newPos.pos, LONG (newPos.usedGroups) * TSIZE(dataSys.onePos));
v.int := MagicDOS.Fclose (grFile);
END;
ELSE
RETURN FALSE;
END;
RETURN TRUE;
END WriteGrPos;
PROCEDURE updateGrPos();
VAR cGrp : INTEGER;
pos : CARDINAL;
isNew : BOOLEAN;
BEGIN
IF ~ReadGrPos (isNew)
THEN
RETURN
END;
(* Jetzt mal sehen, welche Version wir haben *)
IF ~isNew
THEN
cGrp := currentGroup;
(*
IF currentGroup = dataSys.private
THEN
cGrp := 0
ELSE
cGrp := currentGroup + 1;
END;
*)
pos := grPos.pos[cGrp, aktuellePos];
pos := newNums[pos];
IF (msgCounter > 0)
THEN
IF pos > msgCounter-1
THEN
pos := msgCounter-1
END;
ELSE
pos := 1
END;
grPos.pos[cGrp, aktuellePos] := pos;
pos := grPos.pos[cGrp, letztePos];
pos := newNums[pos];
IF (msgCounter > 0)
THEN
IF (pos > msgCounter-1)
THEN
pos := msgCounter-1
END;
ELSE
pos := 1;
END;
grPos.pos[cGrp, letztePos] := pos;
pos := grPos.pos[cGrp, neuePos];
IF (pos = (msgCounter+deleted+badMsg))
THEN
pos := msgCounter
ELSE
pos := (newNums[pos]);
IF (msgCounter > 0)
THEN
IF (pos > msgCounter-1) & (pos # dataSys.empty)
THEN pos := msgCounter-1
END;
ELSE
pos := 1;
END;
END;
grPos.pos[cGrp, neuePos] := pos ;
grPos.pos[cGrp, unreadPos] := firstUnread;
grPos.pos[cGrp, unreadCount] := unreadCounter;
ELSE
(* neue Version vom Gruppen.POS *)
(* Jetzt Daten wandeln *)
cGrp := currentGroup;
pos := GetOnePos (cGrp, dataSys.aktuellePos);
pos := newNums[pos];
IF (msgCounter > 0)
THEN
IF pos > msgCounter-1
THEN
pos := msgCounter-1
END;
ELSE
pos := 1
END;
SetOnePos (cGrp, dataSys.aktuellePos, pos);
pos := GetOnePos (cGrp, dataSys.letztePos);
pos := newNums[pos];
IF (msgCounter > 0)
THEN
IF (pos > msgCounter-1)
THEN
pos := msgCounter-1
END;
ELSE
pos := 1;
END;
SetOnePos (cGrp, dataSys.letztePos, pos);
pos := GetOnePos (cGrp, dataSys.neuePos);
IF (pos = (msgCounter+deleted+badMsg))
THEN
pos := msgCounter
ELSE
pos := (newNums[pos]);
IF (msgCounter > 0)
THEN
IF (pos > msgCounter-1) & (pos # dataSys.empty)
THEN pos := msgCounter-1
END;
ELSE
pos := 1;
END;
END;
SetOnePos (cGrp, dataSys.neuePos, pos);
SetOnePos (cGrp, dataSys.unreadPos, firstUnread);
SetOnePos (cGrp, dataSys.unreadCount, unreadCounter);
END;
v.bool := WriteGrPos (isNew);
FreeGrPos();
END updateGrPos;
PROCEDURE deleteInGroup (group: PutzTypes.ptrGrEntry;
VAR options: PutzTypes.putzOptsRec;
mode: PutzTypes.delMode): BOOLEAN;
VAR i : CARDINAL;
ch : CHAR;
oCurrGr : INTEGER;
rdB : LONGCARD;
res : INTEGER;
BEGIN
hasFileLocking := MagicCookie.FindCookie (MagicCookie.DosFlock, v.lcard);
currentGroup := group^.info^.catNumber;
stopDelete := FALSE;
CASE mode OF
PutzTypes.dFlags : shouldBeDeleted := deleteByFlags; |
PutzTypes.dDate : shouldBeDeleted := deleteDate; |
PutzTypes.dNum : shouldBeDeleted := deleteNum; |
PutzTypes.dDateAndNum: shouldBeDeleted := deleteDateAndNum; |
ELSE
RETURN FALSE
END;
putzOpts := options;
buf := MagicDOS.Malloc (80000L);
IF buf = NIL THEN
v.int := mtAlerts.Alert (1, "[3][CATPUTZ:|Kein Speicher fr|Messagebuffer frei!][[Abbruch]");
RETURN FALSE
END;
openGroup ();
IF stopDelete
THEN
closeGroup;
v.bool := MFree (buf);
RETURN FALSE
END;
PutzAction.ReInitActionBox (group^.info^.name^, getGroupMsgs());
PutzLog.putTime();
PutzLog.WriteString ("Gruppenwechsel zu ");
PutzLog.WriteString (group^.info^.name^);
PutzLog.WriteString (", ");
PutzLog.WriteCard (getGroupMsgs());
PutzLog.WriteString (" Messages zu bearbeiten mit ");
PutzLog.WriteCard (group^.preBytes);
PutzLog.WriteLine (" Bytes.");
stopDelete := ~PutzAction.TellAction (0,0);
msgCounter := 0;
partDeleted := 0;
badMsg := 0;
deleted := 0;
firstUnread := dataSys.empty;
unreadCounter := 0;
(* newNums initialisieren *)
FOR i := 0 TO 65535 DO
newNums[i] := dataSys.empty;
END;
(* Tab und Par-File lesen *)
BufferTabAndPar();
(* Datenfile buffern *)
BufferDatFile();
PutzAction.ShowBuffStatus (tabBuffered, parBuffered, datBuffered);
PutzLog.putTime();
IF tabBuffered
THEN
PutzLog.WriteString ("TAB-File gebuffert");
ELSE
PutzLog.WriteString ("Nichts gebuffert");
END;
IF parBuffered
THEN
PutzLog.WriteString (", PAR-File gebuffert");
END;
IF datBuffered
THEN
PutzLog.WriteString (", DAT-File gebuffert");
END;
PutzLog.WriteLn;
IF AnzMessages > 0 THEN
(* Neue Files anlegen *)
createNewFiles;
IF stopDelete THEN
closeGroup;
v.int := MagicDOS.Fclose (newDat);
v.int := MagicDOS.Fclose (newTab);
v.int := MagicDOS.Fclose (newPar);
deleteNewFiles;
killBuffer;
v.bool := MFree (buf);
RETURN FALSE
END;
(* dbHeader in par-File schreiben *)
IF ~parBuffered
THEN
ReadBytes (parFile, buf, dataSys.dbHeaderLength, rdB);
WriteBytes (newPar, buf, dataSys.dbHeaderLength);
END;
IF stopDelete THEN
closeGroup;
v.int := MagicDOS.Fclose (newDat);
v.int := MagicDOS.Fclose (newTab);
v.int := MagicDOS.Fclose (newPar);
deleteNewFiles;
killBuffer;
v.bool := MFree (buf);
RETURN FALSE
END;
(* Writebuffer anlegen *)
MakeWriteBuffer(newDat);
(* Lschen starten *)
res := doDelete();
IF datBuffered THEN v.bool := MFree (datBuffer) END;
IF stopDelete OR (res > 0) THEN
closeGroup;
(* Writebuffer schlieen *)
CloseWriteBuffer (newDat);
v.int := MagicDOS.Fclose (newDat);
v.int := MagicDOS.Fclose (newTab);
v.int := MagicDOS.Fclose (newPar);
deleteNewFiles;
killBuffer;
v.bool := MFree (buf);
IF res > 0
THEN
group^.postMsgs := group^.preMsgs;
group^.postBytes:= group^.preBytes;
END;
RETURN ~stopDelete
END;
(* Alte Files schlieen *)
IF parBuffered THEN FlushParam (newPar, newParArray); END;
IF stopDelete THEN
closeGroup;
(* Writebuffer schlieen *)
CloseWriteBuffer (newDat);
v.int := MagicDOS.Fclose (newDat);
v.int := MagicDOS.Fclose (newTab);
v.int := MagicDOS.Fclose (newPar);
deleteNewFiles;
killBuffer;
v.bool := MFree (buf);
RETURN FALSE
END;
IF tabBuffered THEN
FlushTab (newTab, newTabArray);
v.bool := MFree (tabArray);
v.bool := MFree (newTabArray);
END;
(* Writebuffer schlieen *)
CloseWriteBuffer (newDat);
IF stopDelete THEN
v.int := MagicDOS.Fclose (newDat);
v.int := MagicDOS.Fclose (newTab);
v.int := MagicDOS.Fclose (newPar);
deleteNewFiles;
v.bool := MFree (buf);
RETURN FALSE
END;
(* Summeneintrag neu setzen *)
group^.badDel := badMsg;
group^.totalDel := deleted;
group^.partDel := partDeleted;
group^.postMsgs := msgCounter;
group^.postBytes:= FileSize (newDat);
INC (totalEntry.badDel, badMsg);
INC (totalEntry.totalDel, deleted);
INC (totalEntry.partDel, partDeleted);
INC (totalEntry.postMsgs, msgCounter);
INC (totalEntry.postBytes, group^.postBytes);
closeGroup;
v.int := MagicDOS.Fclose (newDat);
v.int := MagicDOS.Fclose (newTab);
v.int := MagicDOS.Fclose (newPar);
IF stopDelete THEN
deleteNewFiles;
v.bool := MFree (buf);
RETURN FALSE
END;
stopDelete := ~PutzAction.TellAction (2,AnzMessages);
IF stopDelete THEN
deleteNewFiles;
v.bool := MFree (buf);
RETURN FALSE
END;
(* Kommentarverkettung neu erstellen *)
PutzLog.putTime();
PutzLog.WriteLine ("Kommentarverkettung neu aufbauen");
linkNewPar();
v.int := MagicDOS.Fclose (newPar);
(* Gruppen.POS updaten *)
updateGrPos;
(* Alte Files lschen und neue umbenennen *)
PutzLog.putTime();
PutzLog.WriteLine ("Gruppendateien umkopieren");
stopDelete := ~PutzAction.TellAction (3,AnzMessages);
IF stopDelete THEN
deleteNewFiles;
v.bool := MFree (buf);
RETURN FALSE
END;
makeNewNames;
PutzLog.putTime();
PutzLog.WriteString ("Gruppe ");
PutzLog.WriteString (group^.info^.name^);
PutzLog.WriteString (" geschlossen, Messages nachher: ");
PutzLog.WriteCard (group^.postMsgs);
PutzLog.WriteString (", Bytes nachher: ");
PutzLog.WriteCard (group^.postBytes);
PutzLog.WriteLn;
PutzLog.WriteLn;
ELSE
closeGroup;
END;
v.bool := MFree (buf);
RETURN TRUE;
END deleteInGroup;
PROCEDURE deleteGroup (group : PutzTypes.ptrGrEntry; noConfirm: BOOLEAN): BOOLEAN;
VAR i, j : INTEGER;
maxNum : CARDINAL;
dat2Name,
tab2Name,
par2Name,
datName,
tabName,
parName : PutzTypes.FileStr;
gName : PutzTypes.PathStr;
bRead : LONGCARD;
res : INTEGER;
pos : CARDINAL;
voidLC : LONGCARD;
found : BOOLEAN;
msg : PutzTypes.FileStr;
grFile : fileHandle;
mE : PutzTypes.ptrGrEntry;
isNew : BOOLEAN;
BEGIN
IF ~noConfirm
THEN
Strings.Assign ('[2][Soll die Gruppe|', msg, v.bool);
Strings.Append (group^.info^.name^, msg, v.bool);
Strings.Append (' wirklich|gelscht werden?][[Ja|[Nein]', msg, v.bool);
IF mtAlerts.Alert (2, msg) = 2
THEN
RETURN FALSE
END;
END;
(* Gruppe lschen *)
(* Erstmal Gruppe mit hchster Nummer herausfinden *)
v.bool := GroupSelect.GroupNumber ('%%&%Ý$(', maxNum);
DEC (maxNum);
(* Dateien lschen und umbenennen *)
buildName (group^.info^.catNumber, gName);
Strings.Concat (MTPaths.DataPath, gName, datName, v.bool);
Strings.Assign (datName, parName, v.bool);
Strings.Assign (datName, tabName, v.bool);
Strings.Append ('.par',parName, v.bool);
Strings.Append ('.dat',datName, v.bool);
Strings.Append ('.tab',tabName, v.bool);
(* Dateien lschen *)
IF NOT (MagicDOS.Fdelete (datName) &
MagicDOS.Fdelete (parName) &
MagicDOS.Fdelete (tabName))
THEN
v.int := mtAlerts.Alert (1,"[3][CATPUTZ:|Konnte nicht alle|Dateien lschen!|Mglicherweise ist die|Gruppe jetzt beschdigt.][[Abbruch]");
RETURN TRUE;
END;
GroupSelect.DeleteGroup (group^.info^.name^);
IF INTEGER(maxNum) > group^.info^.catNumber
THEN
(* Von der letzten Gruppe die Nummer noch ndern
* und die Dateien umbenennen
*)
buildName (maxNum, gName);
Strings.Concat (MTPaths.DataPath, gName, dat2Name, v.bool);
Strings.Assign (dat2Name, par2Name, v.bool);
Strings.Assign (dat2Name, tab2Name, v.bool);
Strings.Append ('.par',par2Name, v.bool);
Strings.Append ('.dat',dat2Name, v.bool);
Strings.Append ('.tab',tab2Name, v.bool);
(* Jetzt Dateien umbennen *)
IF (MagicDOS.Frename (tab2Name, tabName) # 0)
OR (MagicDOS.Frename (par2Name, parName) # 0)
OR (MagicDOS.Frename (dat2Name, datName) # 0)
THEN
v.int := mtAlerts.Alert (1,"[3][CATPUTZ:|Konnte Gruppendateien|nicht umbenennen!|Mglicherweise ist die|Datenbank jetzt beschdigt!][[Abbruch]");
RETURN TRUE;
END;
(* Jetzt die gruppe in der Putzliste suchen *)
Lists.ResetList (putzList);
mE := Lists.NextEntry (putzList);
WHILE mE # NIL DO
IF mE^.info^.catNumber = INTEGER(maxNum)
THEN
mE^.info^.catNumber := group^.info^.catNumber;
GroupSelect.SetNewCatNumber (mE^.info^.name^, group^.info^.catNumber);
mE := NIL;
ELSE
mE := Lists.NextEntry (putzList);
END;
END;
ELSE
(* Gruppen.INF sichern *)
GroupSelect.SaveGruppenInf();
END;
(* Jetzt gruppen.pos noch ndern *)
IF ReadGrPos (isNew)
THEN
(* Jetzt ist das geladen, nderungen vornehmen *)
IF ~isNew
THEN
(* Altes GRUPPEN.POS, alte Routine *)
grPos.pos[group^.info^.catNumber] := grPos.pos[maxNum];
grPos.pos[maxNum,aktuellePos] := dataSys.empty;
grPos.pos[maxNum,neuePos] := 0;
grPos.pos[maxNum,letztePos] := 0;
grPos.pos[maxNum,unreadPos] := 0;
grPos.pos[maxNum,unreadCount] := 0;
ELSE
(* neues Gruppen.POS, etwas anders ndern *)
newPos.pos^[group^.info^.catNumber] := newPos.pos^[maxNum];
DEC (newPos.usedGroups);
END;
v.bool := WriteGrPos (isNew);
FreeGrPos();
END;
(* Genderte Gruppenliste von CAT noch sichern *)
v.bool := GroupSelect.SaveGroupList();
(* Ok, die externen Arbeiten sind fertig. Jetzt folgt der interne Kram *)
(* Eintrag noch aus der Putzliste lschen *)
Lists.ResetList (putzList);
mE := Lists.NextEntry (putzList);
WHILE mE # group DO
mE := Lists.NextEntry (putzList);
END;
Lists.RemoveEntry (putzList, v.bool);
Storage.DEALLOCATE (mE, 0);
RETURN TRUE
END deleteGroup;
END PutzGroup.